﻿using Agile.Infra.Core.Agile.Extensions;
using Agile.Infra.WeiXin.Models;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;

namespace Agile.Infra.WeiXin;

public partial class AppletService
{
    public async Task<GetOpenIDResponse> GetOpenIDAsync(string code)
    {
        if (string.IsNullOrEmpty(code))
            return null;

        // 尝试从缓存获取
        if (_memoryCache.TryGetValue(GetCacheKey(code), out GetOpenIDResponse cachedResponse))
        {
            return cachedResponse;
        }

        // 创建针对当前code的信号量（防止重复请求）
        var semaphore = _codeLocks.GetOrAdd(code, _ => new SemaphoreSlim(1, 1));

        await semaphore.WaitAsync();
        try
        {
            // 双重检查缓存
            if (_memoryCache.TryGetValue(GetCacheKey(code), out cachedResponse))
            {
                return cachedResponse;
            }

            var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, $"{_appleOptions.ServerUrl}/sns/jscode2session?appid={_appleOptions.AppId}&secret={_appleOptions.Secret}&js_code={code}&grant_type=authorization_code");

            var response = await HttpRequestAsync(code, httpRequestMessage);

            var result = response.ToJsonObject<GetOpenIDResponse>();

            // 仅当获取到有效结果时缓存
            if (!string.IsNullOrEmpty(result?.openid))
            {
                _memoryCache.Set(GetCacheKey(code), result, TimeSpan.FromMinutes(30));
            }
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"小程序获取OpenId 请求参数[code={code}]");
        }
        finally
        {
            semaphore.Release();
            _codeLocks.TryRemove(code, out _); // 清理信号量
        }
        return null;
    }
}
